import _ from "lodash";
import { IContainerCmpnt, IWidgetCmpnt, IPageCmpnt } from "xcore/cmpnt/types";

export interface IMeta {
    id: string,
    valueKey: string;
    mdata: Record<string, any>;
    cdata: Record<string, any>;
    refs: Record<string, any>;
    getRef(key: string): any
    setRef(key: string, value: any): void
    // cset: (key: string, value: any) => void;
    // cget: (key: string) => any;
    find(key: string): any;
    set: (key: string, value: any) => void;
    get: (key: string) => any;
    remove: (key: string) => void;
    getId: () => string;

}
export function createMetaObject(cmpnt: IContainerCmpnt | IWidgetCmpnt | IPageCmpnt, data: Record<string, any>): IMeta {

    let isMdata = !data || ("mdata" in data && "id" in data && "valueKey" in data);
    return {
        id: isMdata ? data.id : cmpnt.id,
        valueKey: isMdata ? data.valueKey : cmpnt.valueKey,
        mdata: isMdata ? data.mdata : data || {},
        refs: {},
        cdata: isMdata ? data.cdata : {},
        getRef(key: string): any {
            return this.refs[key];
        },
        setRef(key: string, value: any): void {
            this.refs[key] = value;
        },


        set(key: string, value: any): void {
            this.mdata[key] = value;
        },

        get(key: string): any {
            return _.get(this.mdata, key);
        },
        find(key: string): any {
            const findObj = (key: string, obj: any): any => {
                if (obj && typeof obj === "object") {
                    const value = obj[key];
                    if (value !== undefined) {
                        return value;
                    }
                    for (const k in obj) {
                        const result = findObj(key, obj[k]);
                        if (result !== undefined) {
                            return result;
                        }
                    }
                }
            }
            return findObj(key, this.mdata)
        },
        remove(key: string): void {
            const removeObj = (key: string, obj: any) => {
                if (obj && typeof obj === "object") {
                    const value = obj[key];
                    if (value !== undefined) {
                        delete obj[key];
                        return;
                    }
                    _.keys(obj).forEach(k => {
                        removeObj(key, obj[k]);
                    })
                }else{
                    delete obj[key];
                }
            }
            return removeObj(key, this.mdata)
        },
        getId(): string {
            return this.id;
        },
    }
}
